package tree;

import java.io.IOException;

public class Parser 
{
    private Scanner scnr;
    private Token currentToken;

    public Parser()
    {
        scnr = new Scanner();
    }
    public Node parseTree() throws IOException {
        Node root;
        currentToken=scnr.getNextToken();
        root=program();
        if(currentToken.matchToken(Tag.END))
            return root;
        else
        {
            System.out.println("syntax error: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node program() throws IOException {
        Node nProg=new Node(new Token(Tag.PRO));
        Node nBlock=block();
        nProg.addCld(nBlock);
        return nProg;
    }


    private Node block() throws IOException {
        Node nLB, nDecls, nStmts, nRB, nBlock;

        nBlock=new Node(new Token(Tag.BLO));

        if(currentToken.matchToken(Tag.LB))
        {

            nLB=new Node(currentToken);
            currentToken=scnr.getNextToken();
            nDecls=decls();
            nStmts=stmts();

            if(currentToken.matchToken(Tag.RB))
            {

                nRB=new Node(currentToken);
                currentToken=scnr.getNextToken();

                nBlock.addCld(nLB);
                nBlock.addCld(nDecls);
                nBlock.addCld(nStmts);
                nBlock.addCld(nRB);
                return nBlock;
            }
            else
            {
                System.out.println("expecting }, unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else
        {
            System.out.println("expecting {, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node decls() throws IOException {
        Node nDecls, nDecl, nDeclsCld, nEps;

        nDecls=new Node(new Token(Tag.DECLS));

        if(currentToken.matchToken(Tag.INT) || currentToken.matchToken(Tag.BOOL))
        {
            nDecl=decl();
            nDeclsCld=decls();
            nDecls.addCld(nDecl);
            nDecls.addCld(nDeclsCld);
            return nDecls;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nDecls.addCld(nEps);
            return nDecls;
        }
    }

    private Node decl() throws IOException {
        Node nDecl, nType, nId, nSc;
        nDecl=new Node(new Token(Tag.DECL));

        if(currentToken.matchToken(Tag.INT) || currentToken.matchToken(Tag.BOOL))
        {
            nType=type();

            if(currentToken.matchToken(Tag.ID))
            {
                nId=new Node(currentToken);
                currentToken=scnr.getNextToken();
                if(currentToken.matchToken(Tag.SC))
                {
                    nSc=new Node(currentToken);
                    currentToken=scnr.getNextToken();
                    nDecl.addCld(nType);
                    nDecl.addCld(nId);
                    nDecl.addCld(nSc);
                    return nDecl;
                }
                else
                {
                    System.out.println("expecting ;, unmatched: line " + scnr.line); //error
                    System.exit(-1);
                }
            }
            else
            {
                System.out.println("expecting identifier, unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else
        {
            System.out.println("expecting type int or bool, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node type() throws IOException {
        Node nType, nBasic, nTypep;
        nType = new Node(new Token(Tag.TYP));

        if(currentToken.matchToken(Tag.INT) || currentToken.matchToken(Tag.BOOL))
        {
            nBasic=basic();
            nTypep=typep();
            nType.addCld(nBasic);
            nType.addCld(nTypep);
            return nType;
        }
        else
        {
            System.out.println("expecting type int or bool, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node typep() throws IOException {
        Node nTypep, nLsb, nNum, nRsb, nTypepCld, nEps;
        nTypep=new Node(new Token(Tag.TYPP));

        if(currentToken.matchToken(Tag.LSB))
        {
            nLsb=new Node(currentToken);
            currentToken=scnr.getNextToken();

            if(currentToken.matchToken(Tag.NUM))
            {
                nNum=new Node(currentToken);
                currentToken=scnr.getNextToken();

                if(currentToken.matchToken(Tag.RSB))
                {
                    currentToken=scnr.getNextToken();
                    nRsb=new Node(currentToken);
                    nTypepCld=typep();
                    nTypep.addCld(nLsb);
                    nTypep.addCld(nNum);
                    nTypep.addCld(nRsb);
                    nTypep.addCld(nTypepCld);
                    return nTypep;
                }
                else
                {
                    System.out.println("expecting ], unmatched: line " + scnr.line); //error
                    System.exit(-1);
                }
            }
            else
            {
                System.out.println("expecting integer number, unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
            return null;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nTypep.addCld(nEps);
            return nTypep;
        }
    }

    private Node basic() throws IOException {
        Node nBasic;
        nBasic = new Node(new Token(Tag.BASIC));

        if(currentToken.matchToken(Tag.INT) || currentToken.matchToken(Tag.BOOL))
        {
            nBasic.addCld(new Node(currentToken));
            currentToken=scnr.getNextToken();
            return nBasic;
        }
        else
        {
            System.out.println("expecting type int or bool, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node stmts() throws IOException {
        Node nStmts, nStmt, nStmtsCld, nEps;
        nStmts=new Node(new Token(Tag.STMTS));

        if(currentToken.matchToken(Tag.IF) ||
                currentToken.matchToken(Tag.WHILE) ||
                currentToken.matchToken(Tag.DO) ||
                currentToken.matchToken(Tag.BREAK) ||
                currentToken.matchToken(Tag.LB) ||
                currentToken.matchToken(Tag.ID) )
        {
            nStmt=stmt();
            nStmtsCld=stmts();

            nStmts.addCld(nStmt);
            nStmts.addCld(nStmtsCld);
            return nStmts;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nStmts.addCld(nEps);
            return nStmts;
        }
    }

    private Node stmt() throws IOException {
        Node nStmt, nLoc, nSet, nBexpr, nIf, nLp, nRp, nStmtCld, nWhile, nDo, nBreak, nBlock, nSc;
        nStmt=new Node(new Token(Tag.STMT));

        if(currentToken.matchToken(Tag.IF))
        {
            nIf=new Node(currentToken);
            currentToken=scnr.getNextToken();
            if(currentToken.matchToken(Tag.LP))
            {
                nLp=new Node(currentToken);
                currentToken=scnr.getNextToken();

                nBexpr=bexpr();

                if(currentToken.matchToken(Tag.RP))
                {
                    nRp=new Node(currentToken);
                    currentToken=scnr.getNextToken();
                    nStmtCld=stmt();

                    nStmt.addCld(nIf);
                    nStmt.addCld(nLp);
                    nStmt.addCld(nBexpr);
                    nStmt.addCld(nRp);
                    nStmt.addCld(nStmtCld);
                    return nStmt;
                }
                else
                {
                    System.out.println("expecting ), unmatched: line " + scnr.line); //error
                    System.exit(-1);
                }
            }
            else
            {
                System.out.println("expecting (, unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else if(currentToken.matchToken(Tag.WHILE))
        {
            nWhile=new Node(currentToken);
            currentToken=scnr.getNextToken();

            if(currentToken.matchToken(Tag.LP))
            {
                nLp=new Node(currentToken);
                currentToken=scnr.getNextToken();

                nBexpr=bexpr();

                if(currentToken.matchToken(Tag.RP))
                {
                    nRp=new Node(currentToken);
                    currentToken=scnr.getNextToken();

                    nStmtCld=stmt();

                    nStmt.addCld(nWhile);
                    nStmt.addCld(nLp);
                    nStmt.addCld(nBexpr);
                    nStmt.addCld(nRp);
                    nStmt.addCld(nStmtCld);
                    return nStmt;
                }
                else
                {
                    System.out.println("expecting ), unmatched: line " + scnr.line); //error
                    System.exit(-1);
                }
            }
            else
            {
                System.out.println("expecting (, unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else if(currentToken.matchToken(Tag.DO))
        {
            nDo=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nStmtCld=stmt();

            if(currentToken.matchToken(Tag.WHILE))
            {
                nWhile=new Node(currentToken);
                currentToken=scnr.getNextToken();

                if(currentToken.matchToken(Tag.LP))
                {
                    nLp=new Node(currentToken);
                    currentToken=scnr.getNextToken();

                    nBexpr=bexpr();

                    if(currentToken.matchToken(Tag.RP))
                    {
                        nRp=new Node(currentToken);
                        currentToken=scnr.getNextToken();

                        if(currentToken.matchToken(Tag.SC))
                        {
                            nSc=new Node(currentToken);
                            currentToken=scnr.getNextToken();

                            nStmt.addCld(nDo);
                            nStmt.addCld(nStmtCld);
                            nStmt.addCld(nWhile);
                            nStmt.addCld(nLp);
                            nStmt.addCld(nBexpr);
                            nStmt.addCld(nRp);
                            nStmt.addCld(nSc);
                            return nStmt;
                        }
                        else
                        {
                            System.out.println("expecting ;, unmatched: line " + scnr.line); //error
                            System.exit(-1);
                        }
                    }
                    else
                    {
                        System.out.println("expecting ), unmatched: line " + scnr.line); //error
                        System.exit(-1);
                    }
                }
                else
                {
                    System.out.println("expecting (, unmatched: line " + scnr.line); //error
                    System.exit(-1);
                }
            }
            else
            {
                System.out.println("expecting while, unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else if(currentToken.matchToken(Tag.BREAK))
        {
            nBreak=new Node(currentToken);
            currentToken=scnr.getNextToken();

            if(currentToken.matchToken(Tag.SC))
            {
                nSc=new Node(currentToken);
                currentToken=scnr.getNextToken();

                nStmt.addCld(nBreak);
                nStmt.addCld(nSc);
                return nStmt;
            }
            else
            {
                System.out.println("expecting ;, unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else if(currentToken.matchToken(Tag.LB))
        {
            nBlock=new Node(new Token(Tag.BLO));
            nBlock=block();
            nStmt.addCld(nBlock);
            return nStmt;
        }
        else if(currentToken.matchToken(Tag.ID))
        {
            nLoc=loc();

            if(currentToken.matchToken(Tag.SET))
            {
                nSet=new Node(currentToken);
                currentToken=scnr.getNextToken();

                nBexpr=bexpr();

                if(currentToken.matchToken(Tag.SC))
                {
                    nSc=new Node(currentToken);
                    currentToken=scnr.getNextToken();

                    nStmt.addCld(nLoc);
                    nStmt.addCld(nSet);
                    nStmt.addCld(nBexpr);
                    nStmt.addCld(nSc);
                    return nStmt;
                }
                else
                {
                    System.out.println("expecting ;, unmatched: line " + scnr.line); //error
                    System.exit(-1);
                }
            }
            else
            {
                System.out.println("expecting =, unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else
        {
            System.out.println("expecting one of if, while, do, break, { or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node loc() throws IOException {
        Node nLoc, nId, nLocp;
        nLoc=new Node(new Token(Tag.LOC));

        if(currentToken.matchToken(Tag.ID))
        {
            nId=new Node(currentToken);
            currentToken = scnr.getNextToken();

            nLocp=locp();

            nLoc.addCld(nId);
            nLoc.addCld(nLocp);
            return nLoc;
        }
        else
        {
            System.out.println("expecting identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node locp() throws IOException {
        Node nLocp, nLsb, nAexpr, nRsb, nLocpCld, nEps;
        nLocp=new Node(new Token(Tag.LOCP));

        if(currentToken.matchToken(Tag.LSB))
        {
            nLsb=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nAexpr=aexpr();

            if(currentToken.matchToken(Tag.RSB))
            {
                nRsb=new Node(currentToken);
                currentToken=scnr.getNextToken();

                nLocpCld=locp();

                nLocp.addCld(nLsb);
                nLocp.addCld(nAexpr);
                nLocp.addCld(nRsb);
                nLocp.addCld(nLocpCld);
                return nLocp;
            }
            else
            {
                System.out.println("expecting ], unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nLocp.addCld(nEps);
            return nLocp;
        }
        return null;
    }

    private Node bexpr() throws IOException {
        Node nBexpr, nJoin, nBexprp;
        nBexpr=new Node(new Token(Tag.BEXP));

        if(currentToken.matchToken(Tag.NOT) ||
                currentToken.matchToken(Tag.SUB) ||
                currentToken.matchToken(Tag.LP) ||
                currentToken.matchToken(Tag.TRUE) ||
                currentToken.matchToken(Tag.FALSE) ||
                currentToken.matchToken(Tag.NUM) ||
                currentToken.matchToken(Tag.ID) )
        {
            nJoin=join();
            nBexprp=bexprp();
            nBexpr.addCld(nJoin);
            nBexpr.addCld(nBexprp);
            return nBexpr;
        }
        else
        {
            System.out.println("expecting one of !, -, (, true, false, number or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node bexprp() throws IOException {
        Node nBexprp, nOr, nJoin, nBexprpCld, nEps;
        nBexprp=new Node(new Token(Tag.BEXPP));

        if(currentToken.matchToken(Tag.OR))
        {
            nOr=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nJoin=join();
            nBexprpCld=bexprp();
            nBexprp.addCld(nOr);
            nBexprp.addCld(nJoin);
            nBexprp.addCld(nBexprpCld);
            return nBexprp;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nBexprp.addCld(nEps);
            return nBexprp;
        }
    }

    private Node join() throws IOException {
        Node nJoin, nEqu, nJoinp;
        nJoin=new Node(new Token(Tag.JOIN));

        if(currentToken.matchToken(Tag.NOT) ||
                currentToken.matchToken(Tag.SUB) ||
                currentToken.matchToken(Tag.LP) ||
                currentToken.matchToken(Tag.TRUE) ||
                currentToken.matchToken(Tag.FALSE) ||
                currentToken.matchToken(Tag.NUM) ||
                currentToken.matchToken(Tag.ID) )
        {
            nEqu=equality();
            nJoinp=joinp();

            nJoin.addCld(nEqu);
            nJoin.addCld(nJoinp);
            return nJoin;
        }
        else
        {
            System.out.println("expecting one of !, -, (, true, false, number or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node joinp() throws IOException {
        Node nJoinp, nAnd, nEqu, nJoinpCld, nEps;
        nJoinp=new Node(new Token(Tag.JOINP));

        if(currentToken.matchToken(Tag.AND))
        {
            nAnd=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nEqu=equality();
            nJoinpCld=joinp();

            nJoinp.addCld(nAnd);
            nJoinp.addCld(nEqu);
            nJoinp.addCld(nJoinpCld);
            return nJoinp;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nJoinp.addCld(nEps);
            return nJoinp;
        }
    }

    private Node equality() throws IOException {
        Node nEqu, nRel, nEqup;
        nEqu=new Node(new Token(Tag.EQU));

        if(currentToken.matchToken(Tag.NOT) ||
                currentToken.matchToken(Tag.SUB) ||
                currentToken.matchToken(Tag.LP) ||
                currentToken.matchToken(Tag.TRUE) ||
                currentToken.matchToken(Tag.FALSE) ||
                currentToken.matchToken(Tag.NUM) ||
                currentToken.matchToken(Tag.ID) )
        {
            nRel=rel();
            nEqup=equalityp();
            nEqu.addCld(nRel);
            nEqu.addCld(nEqup);
            return nEqu;
        }
        else
        {
            System.out.println("expecting one of !, -, (, true, false, number or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node equalityp() throws IOException {
        Node nEqup, nEq, nNe, nRel, nEqupCld, nEps;
        nEqup=new Node(new Token(Tag.EQUP));

        if(currentToken.matchToken(Tag.EQ))
        {
            nEq=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nRel=rel();
            nEqupCld=equalityp();

            nEqup.addCld(nEq);
            nEqup.addCld(nRel);
            nEqup.addCld(nEqupCld);
            return nEqup;
        }
        else if(currentToken.matchToken(Tag.NE))
        {
            nNe=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nRel=rel();
            nEqupCld=equalityp();

            nEqup.addCld(nNe);
            nEqup.addCld(nRel);
            nEqup.addCld(nEqupCld);
            return nEqup;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nEqup.addCld(nEps);
            return nEqup;
        }
    }

    private Node rel() throws IOException {
        Node nRel, nAexpr, nRelp;
        nRel=new Node(new Token(Tag.REL));

        if(currentToken.matchToken(Tag.NOT) ||
                currentToken.matchToken(Tag.SUB) ||
                currentToken.matchToken(Tag.LP) ||
                currentToken.matchToken(Tag.TRUE) ||
                currentToken.matchToken(Tag.FALSE) ||
                currentToken.matchToken(Tag.NUM) ||
                currentToken.matchToken(Tag.ID) )
        {
            nAexpr=aexpr();
            nRelp=relp();

            nRel.addCld(nAexpr);
            nRel.addCld(nRelp);
            return nRel;
        }
        else
        {
            System.out.println("expecting one of !, -, (, true, false, number or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node relp() throws IOException {
        Node nRelp, nLt, nLe, nGt, nGe, nAexpr, nEps;
        nRelp=new Node(new Token(Tag.RELP));

        if(currentToken.matchToken(Tag.LT))
        {
            nLt=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nAexpr=aexpr();

            nRelp.addCld(nLt);
            nRelp.addCld(nAexpr);
            return nRelp;
        }
        else if(currentToken.matchToken(Tag.LE))
        {
            nLe=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nAexpr=aexpr();

            nRelp.addCld(nLe);
            nRelp.addCld(nAexpr);
            return nRelp;
        }
        else if(currentToken.matchToken(Tag.GT))
        {
            nGt=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nAexpr=aexpr();

            nRelp.addCld(nGt);
            nRelp.addCld(nAexpr);
            return nRelp;
        }
        else if(currentToken.matchToken(Tag.GE))
        {
            nGe=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nAexpr=aexpr();

            nRelp.addCld(nGe);
            nRelp.addCld(nAexpr);
            return nRelp;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nRelp.addCld(nEps);
            return nRelp;
        }
    }

    private Node aexpr() throws IOException {
        Node nAexpr, nTerm, nAexprp = null;
        nAexpr=new Node(new Token(Tag.AEXP));

        if(currentToken.matchToken(Tag.NOT) ||
                currentToken.matchToken(Tag.SUB) ||
                currentToken.matchToken(Tag.LP) ||
                currentToken.matchToken(Tag.TRUE) ||
                currentToken.matchToken(Tag.FALSE) ||
                currentToken.matchToken(Tag.NUM) ||
                currentToken.matchToken(Tag.ID) )
        {
            nTerm=term();
            try {
                nAexprp=aexprp();
                nAexpr.addCld(nTerm);
                nAexpr.addCld(nAexprp);
                return nAexpr;
            } catch (IOException e) {
                e.printStackTrace();
            }

        }
        else
        {
            System.out.println("expecting one of !, -, (, true, false, number or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node aexprp() throws IOException {
        Node nAexprp, nAexprpCld, nAdd, nSub, nTerm, nEps;
        nAexprp=new Node(new Token(Tag.AEXPP));

        if(currentToken.matchToken(Tag.ADD))
        {
            nAdd=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nTerm=term();
            nAexprpCld=aexprp();

            nAexprp.addCld(nAdd);
            nAexprp.addCld(nTerm);
            nAexprp.addCld(nAexprpCld);
            return nAexprp;
        }
        else if(currentToken.matchToken(Tag.SUB))
        {
            nSub=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nTerm=term();
            nAexprpCld=aexprp();

            nAexprp.addCld(nSub);
            nAexprp.addCld(nTerm);
            nAexprp.addCld(nAexprpCld);
            return nAexprp;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nAexprp.addCld(nEps);
            return nAexprp;
        }
    }

    private Node term() throws IOException {
        Node nTerm, nUnary, nTermp;
        nTerm = new Node(new Token(Tag.TERM));

        if(currentToken.matchToken(Tag.NOT) ||
                currentToken.matchToken(Tag.SUB) ||
                currentToken.matchToken(Tag.LP) ||
                currentToken.matchToken(Tag.TRUE) ||
                currentToken.matchToken(Tag.FALSE) ||
                currentToken.matchToken(Tag.NUM) ||
                currentToken.matchToken(Tag.ID) )
        {
            nUnary=unary();
            nTermp=termp();

            nTerm.addCld(nUnary);
            nTerm.addCld(nTermp);
            return nTerm;
        }
        else
        {
            System.out.println("expecting one of !, -, (, true, false, number or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node termp() throws IOException {
        Node nTermp, nTermpCld, nMul, nDiv, nUnary, nEps;
        nTermp = new Node(new Token(Tag.TERMP));

        if(currentToken.matchToken(Tag.MUL))
        {
            nMul=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nUnary=unary();
            nTermpCld=termp();

            nTermp.addCld(nMul);
            nTermp.addCld(nUnary);
            nTermp.addCld(nTermpCld);
            return nTermp;
        }
        else if(currentToken.matchToken(Tag.DIV))
        {
            nDiv=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nUnary=unary();
            nTermpCld=termp();

            nTermp.addCld(nDiv);
            nTermp.addCld(nUnary);
            nTermp.addCld(nTermpCld);
            return nTermp;
        }
        else
        {
            nEps=new Node(new Token(Tag.EPS));
            nTermp.addCld(nEps);
            return nTermp;
        }
    }

    private Node unary() throws IOException {
        Node nUnary, nNot, nSub, nUnaryCld, nFac;
        nUnary = new Node(new Token(Tag.UNY));

        if(currentToken.matchToken(Tag.NOT))
        {
            nNot=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nUnaryCld=unary();

            nUnary.addCld(nNot);
            nUnary.addCld(nUnaryCld);
            return nUnary;
        }
        else if(currentToken.matchToken(Tag.SUB))
        {
            nSub=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nUnaryCld=unary();

            nUnary.addCld(nSub);
            nUnary.addCld(nUnaryCld);
            return nUnary;
        }
        else if(currentToken.matchToken(Tag.LP) ||
                currentToken.matchToken(Tag.TRUE) ||
                currentToken.matchToken(Tag.FALSE) ||
                currentToken.matchToken(Tag.NUM) ||
                currentToken.matchToken(Tag.ID) )
        {
            nFac=factor();
            nUnary.addCld(nFac);
            return nUnary;
        }
        else
        {
            System.out.println("expecting one of !, -, (, true, false, number or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

    private Node factor() throws IOException {
        Node nFac, nLp, nRp, nBexpr, nLoc, nNum, nTrue, nFalse;
        nFac=new Node(new Token(Tag.FAC));

        if(currentToken.matchToken(Tag.LP))
        {
            nLp=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nBexpr=bexpr();

            if(currentToken.matchToken(Tag.RP))
            {
                nRp=new Node(currentToken);
                currentToken=scnr.getNextToken();

                nFac.addCld(nLp);
                nFac.addCld(nBexpr);
                nFac.addCld(nRp);
                return nFac;
            }
            else
            {
                System.out.println("expecting ), unmatched: line " + scnr.line); //error
                System.exit(-1);
            }
        }
        else if(currentToken.matchToken(Tag.ID))
        {
            nLoc=loc();
            nFac.addCld(nLoc);
            return nFac;
        }
        else if(currentToken.matchToken(Tag.NUM))
        {
            nNum=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nFac.addCld(nNum);
            return nFac;
        }
        else if(currentToken.matchToken(Tag.TRUE))
        {
            nTrue=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nFac.addCld(nTrue);
            return nFac;
        }
        else if(currentToken.matchToken(Tag.FALSE))
        {
            nFalse=new Node(currentToken);
            currentToken=scnr.getNextToken();

            nFac.addCld(nFalse);
            return nFac;
        }
        else
        {
            System.out.println("expecting one of (, true, false, number or identifier, unmatched: line " + scnr.line); //error
            System.exit(-1);
        }
        return null;
    }

}
 
 
 
 
 